package com.china08.yxyapi.config;

import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;

import java.io.InputStream;
import java.time.LocalDate;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.async.DeferredResult;

import com.fasterxml.classmate.TypeResolver;

import io.swagger.annotations.Api;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Swagger2 Config
 * 
 * @author Ertao.Fang
 *
 */
@Configuration
@EnableSwagger2
@Profile(value = { "dev", "tes" }) // 接口API只在开发和测试环境打开
public class SwaggerConfig {
    /**
     * 通用配置
     * 
     * @param docket
     * @return
     */
    public Docket docketCommon(Docket docket) {
        docket.pathMapping("/")//
                .directModelSubstitute(LocalDate.class, String.class)//
                .genericModelSubstitutes(ResponseEntity.class)//
                .alternateTypeRules(//
                        newRule(typeResolver.resolve(DeferredResult.class,
                                typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
                                typeResolver.resolve(WildcardType.class)))//
                .useDefaultResponseMessages(false)//
                // .globalResponseMessage(RequestMethod.DELETE,
                // globalResponseMessage())//
                // .globalResponseMessage(RequestMethod.GET,
                // globalResponseMessage())//
                // .globalResponseMessage(RequestMethod.POST,
                // globalResponseMessage())//
                // .globalResponseMessage(RequestMethod.PUT,
                // globalResponseMessage())//
                .securitySchemes(newArrayList(apiKey()))//
                .securityContexts(newArrayList(securityContext()))//
                .enableUrlTemplating(true)//
                .ignoredParameterTypes(Model.class)//
                .ignoredParameterTypes(ModelMap.class)//
                .ignoredParameterTypes(Pageable.class);
        return docket;
    }

    /**
     * 所有接口
     * 
     * @return
     */
    @Bean
    public Docket all() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)//
                .groupName("all")//
                .apiInfo(apiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//
                .paths(PathSelectors.any())//
                .build();
        docket = docketCommon(docket);
        return docket;
    }

    /**
     * 工具类接口
     * 
     * @return
     */
    @Bean
    public Docket utilApi() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)//
                .groupName("util")//
                .apiInfo(apiInfo())//
                .select()//
                // .apis(RequestHandlerSelectors.any())//
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//
                .paths(PathSelectors.ant("/api/util/**"))//
                .build();//
        docket = docketCommon(docket);
        return docket;
    }

    /**
     * 业务接口:所有
     * 
     * @return
     */
    @Bean
    public Docket api3Api() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)//
                .groupName("api3-all")//
                .apiInfo(apiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//
                .paths(PathSelectors.ant("/api3/**"))//
                .build();//
        docket = docketCommon(docket);
        return docket;
    }

    /**
     * 业务接口:v01
     * 
     * @return
     */
    @Bean
    public Docket v01Api() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)//
                .groupName("api3-v01")//
                .apiInfo(apiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//
                .paths(PathSelectors.ant("/api3/v01/**"))//
                .build();//
        docket = docketCommon(docket);
        return docket;
    }

    /**
     * 业务接口:v02
     * 
     * @return
     */
    @Bean
    public Docket v02Api() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)//
                .groupName("api3-v02")//
                .apiInfo(apiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//
                .paths(PathSelectors.ant("/api3/v02/**"))//
                .build();//
        docket = docketCommon(docket);
        return docket;
    }

    /**
     * 用户接口
     * 
     * @return
     */
    @Bean
    public Docket userApi() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)//
                .groupName("用户接口")//
                .apiInfo(apiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//
                .paths(PathSelectors.ant("/api3/**/user/**"))//
                .build();//
        docket = docketCommon(docket);
        return docket;
    }

    @Autowired
    private TypeResolver typeResolver;

    private ApiKey apiKey() {
        // return new ApiKey("mykey", "api_key", "header");
        // Sending Authorization: Bearer <token> header
        return new ApiKey("mykey", "Authorization", "header");
    }

    private SecurityContext securityContext() {
        // return
        // SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("/anyPath.*"))
        // .build();
        return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("/*")).build();
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return newArrayList(new SecurityReference("mykey", authorizationScopes));
    }

    List<ResponseMessage> globalResponseMessage() {
        return newArrayList(
                // 4xx 客户端异常
                // 400 参数错误
                new ResponseMessageBuilder()//
                        .code(400)//
                        .message("Bad Request(参数错误)")//
                        .responseModel(new ModelRef("Error"))//
                        .build(),
                // 401 未认证
                new ResponseMessageBuilder()//
                        .code(401)//
                        .message("Unauthorized(未认证)")//
                        .responseModel(new ModelRef("Error"))//
                        .build(),
                // 403 未授权
                new ResponseMessageBuilder()//
                        .code(403)//
                        .message("Forbidden(未授权)")//
                        .responseModel(new ModelRef("Error"))//
                        .build(),
                // 404 未找到服务
                new ResponseMessageBuilder()//
                        .code(404)//
                        .message("Not Found(未找到)")//
                        .responseModel(new ModelRef("Error"))//
                        .build(),
                // 405 Method Not Allowed
                new ResponseMessageBuilder()//
                        .code(405)//
                        .message("Method Not Allowed(不允许使用该方法)")//
                        .responseModel(new ModelRef("Error"))//
                        .build(),
                // 415 不支持的媒体类型
                new ResponseMessageBuilder()//
                        .code(415)//
                        .message("Unsupported Media Type")//
                        .build(),
                // 5xx 服务器端异常
                // 500 服务器内部错误
                new ResponseMessageBuilder()//
                        .code(500)//
                        .message("Internal Server Error(服务器内部错误)")//
                        .responseModel(new ModelRef("Error"))//
                        .build()

        );
    }

    private ApiInfo apiInfo() {
        InputStream in = this.getClass().getResourceAsStream("/static/ApiInfo.html");
        List<String> lines = newArrayList();
        try {
            lines = IOUtils.readLines(in);
        } catch (Exception e) {
        }
        String description = "";
        for (String line : lines) {
            description += line;
        }
        return new ApiInfoBuilder()//
                .title("云校-云平台2.0")//
                .description(description)//
                // .description("--- 描述信息 ---" //
                // + "400 Bad Request(参数错误)" //
                // + "401 Unauthorized(未认证)" //
                // + "403 Forbidden(未授权)" //
                // + "404 Not Found(未找到)"//
                // + "405 Method Not Allowed(不允许使用该方法)" //
                // + "415 Unsupported Media Type" //
                // + "500 Internal Server Error(服务器内部错误)")//
                .termsOfServiceUrl("https://www.91yunxiao.com")//
                .contact(new Contact("云校(北京)科技有限公司", "https://www.91yunxiao.com", ""))
                // .license("Apache License Version 2.0")
                // .licenseUrl("https://github.com/springfox/springfox/blob/master/LICENSE").version("2.0")
                .build();
    }

    // @Bean
    // SecurityConfiguration security() {
    // return new SecurityConfiguration("test-app-client-id",
    // "test-app-client-secret", "test-app-realm", "test-app",
    // "apiKey", ApiKeyVehicle.HEADER, ",", ""/* scope separator */);
    // }

    // @Bean
    // UiConfiguration uiConfig() {
    // return new UiConfiguration("validatorUrl");
    // }

}
